package com.cheney.common.sensitive.core;

import ch.qos.logback.classic.pattern.MessageConverter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import com.cheney.common.sensitive.handler.LogbackMessageHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

public class LogbackCoreConverter extends MessageConverter {
    
    private static final Logger LOGGER = LoggerFactory.getLogger(LogbackCoreConverter.class);

    /** 脱敏处理器 */
    private static LogbackMessageHandler handler;
    
    private static final Set<String> INCLUDE_PACKAGE_PREFIX = new HashSet<>();
    
    private static final Set<String> EXCLUDE_PACKAGE_PREFIX = new HashSet<>();
    
    
    @Override
    public String convert(ILoggingEvent event) {
        StringBuilder sb = new StringBuilder();
        format(event, sb);
        return sb.toString();
    }
    
    /**
     * 进行脱敏
     */
    public void format(final ILoggingEvent event, final StringBuilder toAppendTo){
        String message = event.getMessage();
        if (message == null) {
            return;
        }
        // loggerName形如 org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter, 即:创建logger时所指定的Class的全类名
        String loggerName = event.getLoggerName();
        // 不需要脱敏
        boolean skip = handler == null || EXCLUDE_PACKAGE_PREFIX.stream().anyMatch(loggerName::startsWith);
        String formattedMessage = event.getFormattedMessage();
        if (skip) {
            toAppendTo.append(formattedMessage);
            return;
        }
        boolean needDesensitize = INCLUDE_PACKAGE_PREFIX.stream().anyMatch(loggerName::startsWith);
        if (needDesensitize) {
            // 需要脱敏
            int length = toAppendTo.length();
            try {
                handler.desensitize(event, message, toAppendTo);
            } catch (Throwable e) {
                toAppendTo.setLength(length);
                toAppendTo.append(formattedMessage);
            }
        } else {
            // 不需要脱敏
            toAppendTo.append(formattedMessage);
        }
    }
    
    static void setHandler(LogbackMessageHandler handler) {
        LogbackCoreConverter.handler = handler;
    }
    
    static void addIncludePackagePrefix(Collection<String> c) {
        LogbackCoreConverter.INCLUDE_PACKAGE_PREFIX.addAll(c);
    }
    
    static void addExcludePackagePrefix(Collection<String> c) {
        LogbackCoreConverter.EXCLUDE_PACKAGE_PREFIX.addAll(c);
    }
}